﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using JuCheap.Core.Data;
using JuCheap.Core.Data.Entity;
using JuCheap.Core.Infrastructure;
using JuCheap.Core.Infrastructure.Extentions;
using JuCheap.Core.Interfaces;
using JuCheap.Core.Models;
using JuCheap.Core.Models.Filters;
using JuCheap.Core.Models.ViewModels;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json;
using System.Configuration;

namespace JuCheap.Core.Services.AppServices
{
    public class DefaultRepository : IRepository
    {
        private readonly JuCheapContext _cheapContext;
        private readonly IModelEntityMapper _entityMapper;
        private readonly IHttpClientFactory _httpClientFactory;
        private readonly IFileLocationProvider _fileLocationProvider;

        public DefaultRepository(JuCheapContext cheapContext, IModelEntityMapper entityMapper, IHttpClientFactory httpClientFactory, IFileLocationProvider fileLocationProvider)
        {
            _cheapContext = cheapContext;
            _entityMapper = entityMapper;
            _httpClientFactory = httpClientFactory;
            _fileLocationProvider = fileLocationProvider;
        }

        public async Task<DepartmentGroupWorker> GetDepartmentGroupWoker(int groupID)
        {
            var departmentGroup = await _cheapContext.DepartmentGroupWorkers.FirstOrDefaultAsync(d => d.DepartmentGroupId == groupID);

            return departmentGroup;
        }

        public async Task<PagedResult<WorkerViewModel>> GetWorkers(WorkerFilter filter)
        {
            IQueryable<Worker> workers = _cheapContext.Workers
                .Include(w => w.Company)
                .Include(w => w.JobPosition)
                .ThenInclude(j => j.JobPositionType);

           
            if (filter.id.HasValue)
            {
                var worker = await workers.FirstAsync(w => w.Id == filter.id);
                var departmentGroup = await _cheapContext.DepartmentGroupWorkers.FirstOrDefaultAsync(d => d.WorkerId == worker.Id);

                return SinglePageResult(new WorkerViewModel
                {
                    Birthday = worker.Birthday,
                    CardType = (int)worker.CardType,
                    CompanyId = worker.Company.Id,
                    CardNumber = worker.CardNumber,
                    CompanyName = worker.Company.Name,
                    Email = worker.Email,
                    ExtenralId = worker.ExtenralId,
                    Gender = (int)worker.Gender,
                    GroupIds = departmentGroup==null ? "" : departmentGroup.DepartmentGroupId.ToString(),
                    Id = worker.Id,
                    IdentificationHeadImageUrl = worker.IdentificationHeadImageUrl,
                    JobPositionId = worker.JobPosition.Id,
                    JobPositionName = worker.JobPosition.Name,
                    JobPositionTypeId = worker.JobPosition.JobPositionType.Id,
                    JobPositionTypeName = worker.JobPosition.JobPositionType.Name,
                    Remark = worker.Remark,
                    UserHeadImageUrl = worker.UserHeadImageUrl,
                    PhoneNumber = worker.PhoneNumber,
                    Name = worker.Name,
                    NickName = worker.NickName,
                    Status = worker.Status,//ht20190519
                });
            }

            if (!string.IsNullOrEmpty(filter.name))
            {
                workers = workers.Where(w => w.Name.Contains(filter.name));
            }
            if (!string.IsNullOrEmpty(filter.CompanyId))
            {
                workers = workers.Where(w => w.CompanyId == Convert.ToInt32(filter.CompanyId));
            }
            //if (!string.IsNullOrEmpty(filter.JobPositionTypeId))
            //{
            //    workers = workers.Where(w => w.JobPosition.Id == Convert.ToInt32(filter.JobPositionTypeId));
            //}
            if (!string.IsNullOrEmpty(filter.JobPositionName))
            {
                workers = workers.Where(w => w.JobPosition.Name.Contains(filter.JobPositionName));
            }
            return await workers.Select(worker => new WorkerViewModel
            {
                Birthday = worker.Birthday,
                CardType = (int)worker.CardType,
                CompanyId = worker.Company.Id,
                CardNumber = worker.CardNumber,
                CompanyName = worker.Company.Name,
                Email = worker.Email,
                ExtenralId = worker.ExtenralId,
                Gender = (int)worker.Gender,
                Id = worker.Id,
                IdentificationHeadImageUrl = worker.IdentificationHeadImageUrl,
                JobPositionId = worker.JobPosition.Id,
                JobPositionName = worker.JobPosition.Name,
                JobPositionTypeId = worker.JobPosition.JobPositionType.Id,
                JobPositionTypeName = worker.JobPosition.JobPositionType.Name,
                Remark = worker.Remark,
                UserHeadImageUrl = worker.UserHeadImageUrl,
                PhoneNumber = worker.PhoneNumber,
                Name = worker.Name,
                NickName = worker.NickName,
                Status = worker.Status //ht20190519
            }).PagingAsync(filter.page, filter.rows);
        }

        public async Task<WorkerViewModel> AddWorker(WorkerViewModel worker)
        {
            var company = await _cheapContext.Companies.FindAsync(worker.CompanyId);
            var position = await _cheapContext.JobPositions.FindAsync(worker.JobPositionId);
            //var positionType = await _cheapContext.JobPositionTypes.FindAsync(worker.JobPositionTypeId);

            if (company == null || position == null)
            {
                throw new DomainException("公司或岗位不存在");
            }

            var entity = new Worker
            {
                Birthday = worker.Birthday,
                CardNumber = worker.CardNumber,
                CardType = (CardType)worker.CardType,
                Company = company,
                CreateDateTime = DateTime.Now,
                Email = worker.Email,
                ExtenralId = worker.ExtenralId,
                Gender = (Gender)worker.Gender,
                IdentificationHeadImageUrl = worker.IdentificationHeadImageUrl,
                JobPosition = position,
                //JobPositionType = positionType,
                Name = worker.Name,
                NickName = worker.NickName,
                PhoneNumber = worker.PhoneNumber,
                UserHeadImageUrl = worker.UserHeadImageUrl,
                Remark = worker.Remark,//ht20190519
                Status = worker.Status,
                
            };

            _cheapContext.Workers.Add(entity);

            var client = _httpClientFactory.CreateClient("api");
            var mulitpart = await BuildWorkerContent(worker);
            var response = await client.PostAsync("api/v1/user", mulitpart);
            var sworker = await EnsureSuccess(response);

            entity.RemoteId = sworker.Data.id;
            await _cheapContext.SaveChangesAsync();

            var entityGroup = new DepartmentGroupWorker()
            {
                WorkerId = entity.Id,
                DepartmentGroupId = Convert.ToInt32(worker.GroupIds),
            };
            worker.Id = entity.Id;
            _cheapContext.DepartmentGroupWorkers.Add(entityGroup);
            await _cheapContext.SaveChangesAsync();
            client = _httpClientFactory.CreateClient("api");
            mulitpart = await BuildWorkerContent(worker, entity.RemoteId);
            response = await client.PostAsync($"api/v1/user/update/{entity.RemoteId}", mulitpart);
            sworker = await EnsureSuccess(response);

            //var model = GetWorkers(new WorkerFilter() { id = entity.Id, });
            //await UpdateWorker(model.Result.rows[0]);

            worker.CompanyName = company.Name;
            worker.JobPositionName = position.Name;
            //worker.JobPositionTypeName = positionType.Name;
            worker.Id = entity.Id;
            return worker;
        }

        public async Task<WorkerViewModel> UpdateWorker(WorkerViewModel worker)
        {
            var entity = await _cheapContext.Workers.
                Include(w => w.Company)
                .Include(w => w.JobPosition)
                //.Include(w => w.JobPositionType)
                .FirstOrDefaultAsync(w => w.Id == worker.Id);

            if (entity == null)
            {
                throw new DomainException("员工不存在");
            }

            if (entity.Company.Id != worker.CompanyId)
            {
                entity.Company = await _cheapContext.Companies.FindAsync(worker.CompanyId);
            }

            if (entity.JobPosition.Id != worker.JobPositionId)
            {
                entity.JobPosition = await _cheapContext.JobPositions.FindAsync(worker.JobPositionId);
            }

            //if (entity.JobPositionType.Id != worker.JobPositionTypeId)
            //{
            //    entity.JobPositionType = await _cheapContext.JobPositionTypes.FindAsync(worker.JobPositionTypeId);
            //}

            var client = _httpClientFactory.CreateClient("api");
            MultipartFormDataContent mulitpart = await BuildWorkerContent(worker, entity.RemoteId);
            var response = await client.PostAsync($"api/v1/user/update/{entity.RemoteId}", mulitpart);
            var sworker = await EnsureSuccess(response);
            entity.Name = worker.Name;
            entity.CardType = (CardType)worker.CardType;
            entity.Birthday = worker.Birthday;
            entity.CardNumber = worker.CardNumber;
            entity.NickName = worker.NickName;
            entity.Remark = worker.Remark;
            entity.Email = worker.Email;
            entity.ExtenralId = worker.ExtenralId;
            entity.Gender = (Gender)worker.Gender;
            entity.IdentificationHeadImageUrl = worker.IdentificationHeadImageUrl;
            entity.UserHeadImageUrl = worker.UserHeadImageUrl;
            entity.PhoneNumber = worker.PhoneNumber;
            await _cheapContext.SaveChangesAsync();
            var entityGroup = await _cheapContext.DepartmentGroupWorkers.FirstOrDefaultAsync(w => w.WorkerId == worker.Id);
            entityGroup.DepartmentGroupId = Convert.ToInt32(worker.GroupIds);
            await _cheapContext.SaveChangesAsync();

            worker.CompanyName = entity.Company.Name;
            worker.JobPositionName = entity.JobPosition.Name;
            worker.Status = entity.Status;//ht20190519
            //worker.JobPositionTypeName = entity.JobPositionType.Name;
            return worker;
        }


        public async Task<string> GetAllRecords(string type, string size, string date)
        {
            var client = _httpClientFactory.CreateClient("api");
            var query = new List<KeyValuePair<string, string>>();
            query.Add(KeyValuePair.Create("type", type));
            query.Add(KeyValuePair.Create("size", size));
            if(!string.IsNullOrEmpty(date))
            {
                DateTime dateTime = Convert.ToDateTime(date);
                DateTime start = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 0, 0, 0);
                var utc = new DateTime(1970, 1, 1);
                var st = (start - utc).TotalSeconds;
                var et = (start.AddDays(1) - utc).TotalSeconds;
                query.Add(KeyValuePair.Create("startTime", st.ToString("F0")));
                query.Add(KeyValuePair.Create("endTime", et.ToString("F0")));
            }
            Sign(query);
            var url = $"api/v1/record{BuildUrl(query)}";
            var response = await client.GetAsync(url);
            return await response.Content.ReadAsStringAsync();
        }

        private async Task<MultipartFormDataContent> BuildWorkerContent(WorkerViewModel worker, int remoteId = 0)
        {
            var data = new List<KeyValuePair<string, string>>();
            Sign(data);
            var mulitpart = new MultipartFormDataContent();
            if(!string.IsNullOrEmpty(worker.IdentificationHeadImageUrl))
            {
                var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(_fileLocationProvider.GetAbsoluteLocation(worker.IdentificationHeadImageUrl)));
                fileContent.Headers.Add("Content-Type", "image/jpeg");
                mulitpart.Add(fileContent, "avatarFile", worker.IdentificationHeadImageUrl);
            }
           
            if (worker.Id != 0 && remoteId != 0)
            {
                var groups = await _cheapContext.DepartmentGroupWorkers
                    .Where(gw => gw.WorkerId == worker.Id)
                    .Join(_cheapContext.DepartmentGroups, gw => gw.DepartmentGroupId, g => g.Id, (gw, g) => g)
                    .ToListAsync();
                var newGroups = worker.GroupIds.Split(',').Select(int.Parse)
                    .Join(_cheapContext.DepartmentGroups, gi => gi, g => g.Id, (gi, g) => g)
                    .ToList();
                //groupEntities = groupEntities.FindAll(g => g.Workers.Contains(worker.Id.ToString()));
                //var client = _httpClientFactory.CreateClient("api");
                //var idkv = KeyValuePair.Create("id", remoteId.ToString());
                //data.Add(idkv);
                //var url = BuildUrl(data);
                //var response = await client.GetAsync($"api/v1/user/list{url}");
                //var res = await EnsureSuccess(response);
                //if (res.Data == null)
                //{
                //    throw new DomainException("员工不存在");
                //}
                //var wk = res.Data[0];
                //var groups = new List<KeyValuePair<string, string>>();
                //if (wk.groupList != null)
                //{
                //    foreach (var item in wk.groupList)
                //    {
                //        groups.Add(KeyValuePair.Create("groups", item.id.ToString()));
                //    }
                //}
                foreach (var g in newGroups)
                {
                    //groups.Add(KeyValuePair.Create("groups", g.ToString()));
                    mulitpart.Add(new StringContent(g.RemoteId.ToString()), "groups");
                    //_cheapContext.DepartmentGroupWorkers.Add(new DepartmentGroupWorker { WorkerId = worker.Id, DepartmentGroupId = g.Id });
                }
                if (groups.Count == 0)
                {
                    mulitpart.Add(new StringContent(string.Empty), "groups");
                }

                _cheapContext.DepartmentGroupWorkers.RemoveRange(_cheapContext.DepartmentGroupWorkers.Where(w => w.WorkerId == worker.Id));
                _cheapContext.DepartmentGroupWorkers.AddRange(newGroups.Select(g => new DepartmentGroupWorker { DepartmentGroupId = g.Id, WorkerId = worker.Id }));
                //else
                //{
                //    //mulitpart.Add(new FormUrlEncodedContent(groups), "groups");
                //}
            }
            else
            {
                mulitpart.Add(new StringContent(string.Empty), "groups");
            }
            mulitpart.Add(new StringContent(string.Empty), "icNumber");
            mulitpart.Add(new StringContent(worker.Remark ?? string.Empty), "jobNumber");
            mulitpart.Add(new StringContent(worker.PhoneNumber), "mobile");
            mulitpart.Add(new StringContent(worker.Name), "name");
            mulitpart.Add(new StringContent(worker.Remark ?? string.Empty), "remark");
            mulitpart.Add(new StringContent(data.Find(p => p.Key == "app_key").Value), "app_key");
            mulitpart.Add(new StringContent(data.Find(p => p.Key == "timestamp").Value), "timestamp");
            mulitpart.Add(new StringContent(data.Find(p => p.Key == "sign").Value), "sign");
            return mulitpart;
        }

        public async Task DeleteWorker(int id)
        {
            var entity = await _cheapContext.Workers.FindAsync(id);
            if (entity != null)
            {
                var client = _httpClientFactory.CreateClient("api");
                var query = new List<KeyValuePair<string, string>>();
                Sign(query);
                var url = $"/api/v1/user/delete/{entity.RemoteId}{BuildUrl(query)}";
                var response = await client.GetAsync(url);
                await EnsureSuccess(response);

                _cheapContext.Workers.Remove(entity);
                
                await _cheapContext.SaveChangesAsync();
            }
        }

        public async Task<PagedResult<JobPositionViewModel>> GetJobPositions(JobPositionFilter filter)
        {
            if (filter.id.HasValue)
            {
                IQueryable<JobPosition> position = _cheapContext.JobPositions.Include(p => p.JobPositionType);

                if (filter.id != 0)
                {
                    position = position.Where(p => p.Id == filter.id);
                }

                return await position.Select(p => new JobPositionViewModel
                {
                    Id = p.Id,
                    Name = p.Name,
                    PositionType = p.JobPositionType.Name,
                    PositionTypeId = p.JobPositionType.Id
                }).PagingAsync(filter.page, filter.rows);

            }

            if (filter.JobPositionTypeId != 0)
            {
                IQueryable<JobPosition> position = _cheapContext.JobPositions.Include(p => p.JobPositionType);

                if (filter.JobPositionTypeId != 0)
                {
                    position = position.Where(p => p.JobPositionType.Id == filter.JobPositionTypeId);
                }

                return await position.Select(p => new JobPositionViewModel
                {
                    Id = p.Id,
                    Name = p.Name,
                    PositionType = p.JobPositionType.Name,
                    PositionTypeId = p.JobPositionType.Id
                }).PagingAsync(filter.page, filter.rows);

            }
            IQueryable<JobPosition> positions = _cheapContext.JobPositions.Include(p => p.JobPositionType);

            if (!string.IsNullOrEmpty(filter.name))
            {
                positions = positions.Where(p => p.Name.Contains(filter.name));
            }
            if (filter.JobPositionTypeId != 0)
            {
                positions = positions.Where(p => p.JobPositionType.Id == filter.JobPositionTypeId);
            }
            return await positions.Select(p => new JobPositionViewModel
            {
                Id = p.Id,
                Name = p.Name,
                PositionType = p.JobPositionType.Name,
                PositionTypeId = p.JobPositionType.Id
            }).PagingAsync(filter.page, filter.rows);
        }

        public async Task<JobPositionViewModel> AddJobPosition(JobPositionViewModel jobPosition)
        {
            var positionType = await _cheapContext.JobPositionTypes.FindAsync(jobPosition.PositionTypeId);

            if (positionType == null)
            {
                throw new DomainException("岗位类型不存在");
            }

            var entity = new JobPosition
            {
                CreateDateTime = DateTime.Now,
                JobPositionType = positionType,
                Name = jobPosition.Name
            };

            _cheapContext.JobPositions.Add(entity);

            await _cheapContext.SaveChangesAsync();

            jobPosition.Id = entity.Id;
            jobPosition.PositionType = positionType.Name;
            return jobPosition;
        }

        public async Task<JobPositionViewModel> UpdateJobPosition(JobPositionViewModel jobPosition)
        {
            var entity = await _cheapContext.JobPositions.FindAsync(jobPosition.Id);

            if (entity == null)
            {
                throw new DomainException("岗位不存在");
            }

            var positionTypeId = _cheapContext.Entry(entity).Property<int?>("JobPositionTypeId").CurrentValue;
            if (positionTypeId != jobPosition.PositionTypeId)
            {
                entity.JobPositionType = await _cheapContext.JobPositionTypes.FindAsync(jobPosition.PositionTypeId);
                jobPosition.PositionType = entity.JobPositionType.Name;
            }

            entity.Name = jobPosition.Name;

            await _cheapContext.SaveChangesAsync();

            return jobPosition;
        }

        public async Task DeleteJobPosition(int jobPositionId)
        {
            var entity = await _cheapContext.JobPositions.FindAsync(jobPositionId);

            if (entity != null)
            {
                _cheapContext.JobPositions.Remove(entity);
                await _cheapContext.SaveChangesAsync();
            }
        }

        public async Task<PagedResult<JobPositionTypeViewModel>> GetJobPositionTypes(JobPositionTypeFilter filter)
        {
            if (filter.id.HasValue)
            {
                var jobPositionType = await _cheapContext.JobPositionTypes.FindAsync(filter.id);
                return SinglePageResult(_entityMapper.Map<JobPositionType, JobPositionTypeViewModel>(jobPositionType));
            }

            IQueryable<JobPositionType> jobPositionTypes = _cheapContext.JobPositionTypes;

            if (!string.IsNullOrEmpty(filter.name))
            {
                jobPositionTypes = jobPositionTypes.Where(p => p.Name.Contains(filter.name));
            }

            return await jobPositionTypes.Select(j => _entityMapper.Map<JobPositionType, JobPositionTypeViewModel>(j))
                .PagingAsync(filter.page, filter.rows);
        }

        public async Task<JobPositionTypeViewModel> AddJobPositionType(JobPositionTypeViewModel jobPositionType)
        {
            var entity = new JobPositionType { CreateDateTime = DateTime.Now, Name = jobPositionType.Name };
            _cheapContext.JobPositionTypes.Add(entity);
            await _cheapContext.SaveChangesAsync();
            jobPositionType.Id = entity.Id;
            return jobPositionType;
        }

        public async Task<JobPositionTypeViewModel> UpdateJobPositionType(JobPositionTypeViewModel jobPositionType)
        {
            var entity = await _cheapContext.JobPositionTypes.FindAsync(jobPositionType.Id);

            if (entity == null)
            {
                throw new DomainException("岗位类型不存在");
            }

            entity.Name = jobPositionType.Name;
            await _cheapContext.SaveChangesAsync();

            return jobPositionType;
        }

        public async Task DeleteJobPositionType(int jobPositionTypeId)
        {
            var entity = await _cheapContext.JobPositionTypes.FindAsync(jobPositionTypeId);
            if (entity != null)
            {
                _cheapContext.JobPositionTypes.Remove(entity);
                await _cheapContext.SaveChangesAsync();
            }
        }

        public async Task<PagedResult<HardWareDeviceViewModel>> GetHardWareDevices(HardWareDeviceFilter filter)
        {
            if (filter.id.HasValue)
            {
                var deviceSingle = await _cheapContext.HardWareDevices.FindAsync(filter.id);
                var model = SinglePageResult(_entityMapper.Map<HardWareDevice, HardWareDeviceViewModel>(deviceSingle));
                try
                {
                    var departmentGroup = await _cheapContext.DepartmentGroupDevices.FirstAsync(d => d.HardWareDeviceId == model.rows[0].Id);
                    model.rows[0].GroupIds = departmentGroup.DepartmentGroupId.ToString();
                }
                catch { }

                return model;

            }
            IQueryable<HardWareDevice> devices = _cheapContext.HardWareDevices;

            //var devices = _cheapContext.HardWareDevices;
            if(!string.IsNullOrEmpty(filter.name))
            {
                devices = devices.Where(d=>d.Name.Contains(filter.name));
            }
            if (!string.IsNullOrEmpty(filter.DeviceId))
            {
                devices = devices.Where(d => d.DeviceSn == filter.DeviceId);
            }
            var device = devices.ToList();
            await SyncDeviceFromApi(device);
            return new PagedResult<HardWareDeviceViewModel>(filter.page, filter.rows)
            {
                rows = device.Select(d => _entityMapper.Map<HardWareDevice, HardWareDeviceViewModel>(d)).ToList(),
                records = device.Count
            };
        }

        private async Task SyncDeviceFromApi(List<HardWareDevice> devices)
        {
            var client = _httpClientFactory.CreateClient("api");
            var query = new List<KeyValuePair<string, string>>();
            Sign(query);
            var url = $"api/v1/device{BuildUrl(query)}";
            var response = await client.GetAsync(url);
            var apiRespone = await EnsureSuccess(response);
            var changed = false;
            foreach (var d in apiRespone.Data.data)
            {
                foreach (var dl in devices)
                {
                    if (d.device.sn == dl.DeviceSn)
                    {
                        var s = (DeviceStatus)d.device.status;
                        var id = (string)d.device.id;
                        if (dl.Status != s)
                        {
                            dl.Status = s;
                            changed = true;
                        }

                        if (dl.DeviceId != id)
                        {
                            dl.DeviceId = id;
                            changed = true;
                        }
                    }
                }
            }

            if (changed)
            {
                await _cheapContext.SaveChangesAsync();
            }

        }

        public async Task<HardWareDeviceViewModel> AddHardWareDevice(HardWareDeviceViewModel hardWareDevice)
        {
            // 先把设备添加到本地
            var entity = _entityMapper.Map<HardWareDeviceViewModel, HardWareDevice>(hardWareDevice);

            _cheapContext.HardWareDevices.Add(entity);
            

            // 同步设备id
            await SyncDeviceFromApi(new List<HardWareDevice> { entity });   
            await _cheapContext.SaveChangesAsync();
            // 同步设备组信息
            var groupIds = hardWareDevice.GroupIds.Split(',').Select(int.Parse).ToList();
            var groups = await _cheapContext.DepartmentGroups.ToListAsync();
            var remoteIds = groupIds.Join(groups, gi => gi, g => g.Id, (gi, g) => g.RemoteId).ToList();
            _cheapContext.DepartmentGroupDevices.AddRange(groupIds.Select(gi => new DepartmentGroupDevice { DepartmentGroupId = gi, HardWareDeviceId = entity.Id }));
            await ApiUpdateDevice(entity, remoteIds);
            await _cheapContext.SaveChangesAsync();

            hardWareDevice.Id = entity.Id;
            return hardWareDevice;
        }

        //public async Task<HardWareDeviceViewModel> UpdateHardWareDevice(HardWareDeviceViewModel hardWareDevice)
        //{
        //    var entity = await _cheapContext.HardWareDevices.FindAsync(hardWareDevice.Id);

        //    if (entity == null)
        //    {
        //        throw new DomainException("设备不存在");
        //    }

        //    //_entityMapper.Map(hardWareDevice, entity);
        //    entity.DeviceSn = hardWareDevice.DeviceSn;
        //    entity.Direction = hardWareDevice.Direction;
        //    entity.Name = hardWareDevice.Name;
        //    entity.Location = hardWareDevice.Location;

        //    // 更新组信息
        //    var groups = await _cheapContext.DepartmentGroupDevices
        //        .Where(d => d.HardWareDeviceId == entity.Id)
        //        .Join(_cheapContext.DepartmentGroups, gd => gd.HardWareDeviceId, g => g.Id, (gd, g) => g.RemoteId)
        //        .Join(_cheapContext.DepartmentGroups, gd => gd.DepartmentGroupId, g => g.Id, (gd, g) => g.RemoteId)
        //        .ToListAsync();
        //    await ApiUpdateDevice(entity, groups);
        //    _cheapContext.DepartmentGroupDevices.RemoveRange(_cheapContext.DepartmentGroupDevices.Where(gd => gd.HardWareDeviceId == entity.Id));
        //    _cheapContext.DepartmentGroupDevices.AddRange(hardWareDevice.GroupIds.Split(',').Select(gis => new DepartmentGroupDevice { HardWareDeviceId = entity.Id, DepartmentGroupId = int.Parse(gis) }));

        //    await _cheapContext.SaveChangesAsync();
        //    return hardWareDevice;
        //}

        public async Task<HardWareDeviceViewModel> UpdateHardWareDevice(HardWareDeviceViewModel hardWareDevice)
        {
            var entity = await _cheapContext.HardWareDevices.FindAsync(hardWareDevice.Id);

            if (entity == null)
            {
                throw new DomainException("设备不存在");
            }

            //_entityMapper.Map(hardWareDevice, entity);
            entity.DeviceSn = hardWareDevice.DeviceSn;
            entity.Direction = hardWareDevice.Direction;
            entity.Name = hardWareDevice.Name;
            entity.Location = hardWareDevice.Location;


            _cheapContext.DepartmentGroupDevices.RemoveRange(_cheapContext.DepartmentGroupDevices.Where(gd => gd.HardWareDeviceId == entity.Id));
            _cheapContext.DepartmentGroupDevices.AddRange(hardWareDevice.GroupIds.Split(',').Select(gis => new DepartmentGroupDevice { HardWareDeviceId = entity.Id, DepartmentGroupId = int.Parse(gis) }));

            await _cheapContext.SaveChangesAsync();
            // 更新组信息
            var groups = await _cheapContext.DepartmentGroupDevices
                .Where(d => d.HardWareDeviceId == entity.Id)
                .Join(_cheapContext.DepartmentGroups, gd => gd.DepartmentGroupId, g => g.Id, (gd, g) => g.RemoteId)
                .ToListAsync();
            await ApiUpdateDevice(entity, groups);
            //await ApiUpdateDevice(entity, groups);
            return hardWareDevice;
        }

        private async Task ApiUpdateDevice(HardWareDevice entity, List<int> groups)
        {
            var client = _httpClientFactory.CreateClient("api");
            var data = new List<KeyValuePair<string, string>>
            {
                KeyValuePair.Create("id", entity.DeviceId),
                KeyValuePair.Create("name", entity.Name),
                KeyValuePair.Create("location", entity.Location),
                KeyValuePair.Create("direction", entity.Direction.ToString())
            };
            foreach (var g in groups)
            {
                data.Add(KeyValuePair.Create("groupStaff", g.ToString()));
            }
            Sign(data);
            var response = await client.PostAsync("api/v2/device/update", new FormUrlEncodedContent(data));
            
            await EnsureSuccess(response);
        }

        public async Task DeleteHardWareDevice(int hardWareDeviceId)
        {
            var entity = await _cheapContext.HardWareDevices.FindAsync(hardWareDeviceId);

            if (entity != null)
            {
                var client = _httpClientFactory.CreateClient("api");
                var query = new List<KeyValuePair<string, string>>();
                Sign(query);
                var url = $"/api/v1/device/delete/{entity.DeviceId}{BuildUrl(query)}";
                var response = await client.GetAsync(url);
                //await EnsureSuccess(response);

                _cheapContext.HardWareDevices.Remove(entity);
                await _cheapContext.SaveChangesAsync();
            }
        }


        public async Task ImportWorkerToGroup(IReadOnlyList<KeyValuePair<string, string>> workers)
        {
            var groups = await _cheapContext.DepartmentGroups.ToListAsync();
            var wids = await _cheapContext.Workers.Select(w => new { w.Id, Name = w.PhoneNumber, w.RemoteId }).ToListAsync();
            var gws = workers.GroupBy(kv => kv.Key);
            foreach (var g in gws)
            {
                if (groups.Exists(ig => ig.Name == g.Key))
                {
                    var eg = groups.Find(ig => ig.Name == g.Key);
                    //await UpdateDepartmentGroup(new DepartmentGroupViewModel
                    //{
                    //    Id = eg.Id,
                    //    Devices = eg.Devices.Split(',').Select(i => new HardWareDeviceViewModel { Id = int.Parse(i) }).ToList(),
                    //    OpenCycle = eg.OpenCycle,
                    //    Name = eg.Name,
                    //    Workers = g.Join(wids, kv => kv.Value, w => w.Name, (kv, w) => w.Id).Select(id => new WorkerViewModel { Id = id }).ToList()
                    //});
                    _cheapContext.DepartmentGroupWorkers.AddRange(wids.Select(w => new DepartmentGroupWorker { WorkerId = w.Id, DepartmentGroupId = eg.Id }));
                    await ApiAddUserInGroup(eg.RemoteId, wids.Select(w => w.RemoteId).ToList(), true);
                    await _cheapContext.SaveChangesAsync();
                }
                else
                {
                    //await AddDepartmentGroup(new DepartmentGroupViewModel
                    //{
                    //    Devices = new List<HardWareDeviceViewModel>(),
                    //    Name = g.Key,
                    //    Workers = g.Join(wids, kv => kv.Value, w => w.Name, (kv, w) => w.Id).Select(id => new WorkerViewModel { Id = id }).ToList()
                    //});
                    throw new DomainException($"组: {g.Key} 不存在");
                }
            }
        }

        public async Task<PagedResult<DepartmentGroupViewModel>> GetDepartmentGroups(DepartmentGroupFilter filter)
        {
            if (filter.id.HasValue)
            {
                var departmentGroup = await _cheapContext.DepartmentGroups.FindAsync(filter.id);
                //return SinglePageResult(await ExtratDepartmentGroups(departmentGroup));
                return SinglePageResult(new DepartmentGroupViewModel { Id = departmentGroup.Id, Name = departmentGroup.Name, OpenCycle = departmentGroup.OpenCycle });
            }

            IQueryable<DepartmentGroup> departmentGroups = _cheapContext.DepartmentGroups;
            if(!string.IsNullOrEmpty(filter.name))
            {
                departmentGroups = departmentGroups.Where(d => d.Name.Contains(filter.name));
            }

            var result = await departmentGroups.PagingAsync(filter.page, filter.rows);
            var viewResult = new PagedResult<DepartmentGroupViewModel>
            {
                pagesize = result.pagesize,
                page = result.page,
                records = result.records,
                rows = new List<DepartmentGroupViewModel>()
            };

            foreach (var departmentGroup in result.rows)
            {
                //viewResult.rows.Add(await ExtratDepartmentGroups(departmentGroup));
                viewResult.rows.Add(new DepartmentGroupViewModel { Id = departmentGroup.Id, Name = departmentGroup.Name, OpenCycle = departmentGroup.OpenCycle });
            }

            return viewResult;
        }

        //private async Task<DepartmentGroupViewModel> ExtratDepartmentGroups(DepartmentGroup departmentGroup)
        //{
        //    var workerIds = departmentGroup.Workers.Split(',').Select(int.Parse);
        //    var workers = await _cheapContext.Workers.Where(w => workerIds.Contains(w.Id)).ToListAsync();
        //    var deviceIds = departmentGroup.Devices.Split(',').Select(int.Parse);
        //    var devices = await _cheapContext.HardWareDevices.Where(d => deviceIds.Contains(d.Id)).ToListAsync();

        //    return new DepartmentGroupViewModel
        //    {
        //        Devices = devices.Select(device => _entityMapper.Map<HardWareDevice, HardWareDeviceViewModel>(device)).ToList(),
        //        Workers = workers.Select(worker => _entityMapper.Map<Worker, WorkerViewModel>(worker)).ToList(),
        //        Id = departmentGroup.Id,
        //        Name = departmentGroup.Name,
        //        OpenCycle = departmentGroup.OpenCycle
        //    };
        //}

        public async Task<DepartmentGroupViewModel> AddDepartmentGroup(DepartmentGroupViewModel departmentGroup)
        {

            var cycles = string.Join(',', departmentGroup.OpenCycle.Split(',').Select(GetXingQi));
            var entity = new DepartmentGroup
            {
                Name = departmentGroup.Name,
                OpenCycle = cycles
            };

            var client = _httpClientFactory.CreateClient("api");
            var data = new List<KeyValuePair<string, string>>
            {
                KeyValuePair.Create("name", departmentGroup.Name),
                KeyValuePair.Create("type", "1")
            };
            // 添加群组
            Sign(data);
            var response = await client.PostAsync("api/v1/group", new FormUrlEncodedContent(data));
            var res = await EnsureSuccess(response);
            entity.RemoteId = res.Data.id;

            // 添加员工
            //var wids = departmentGroup.Workers.Select(w => w.Id).ToList();
            //data.Clear();
            //Sign(data);
            //data.Add(KeyValuePair.Create("groupId", entity.RemoteId.ToString()));
            //var workerids = await _cheapContext.Workers.Where(w => wids.Contains(w.Id)).Select(w => w.RemoteId).ToListAsync();
            //foreach (var id in workerids)
            //{
            //    data.Add(KeyValuePair.Create("userIds", id.ToString()));
            //}
            //if (workerids.Count != 0)
            //{
            //    response = await client.PostAsync("api/v1/user/add/group", new FormUrlEncodedContent(data));
            //    await EnsureSuccess(response);
            //}

            //var workers = string.Join(',', wids);
            //var devices = string.Join(',', departmentGroup.Devices.Select(d => d.Id));



            _cheapContext.DepartmentGroups.Add(entity);

            await _cheapContext.SaveChangesAsync();

            departmentGroup.Id = entity.Id;
            return departmentGroup;
        }


        public async Task<DepartmentGroupViewModel> UpdateDepartmentGroup(DepartmentGroupViewModel departmentGroup)
        {
            var entity = await _cheapContext.DepartmentGroups.FindAsync(departmentGroup.Id);

            if (entity == null)
            {
                throw new DomainException("群组不存在");
            }
            //var wids = departmentGroup.Workers.Select(w => w.Id).ToList();
            //var workers = string.Join(',', wids);
            //var devices = string.Join(',', departmentGroup.Devices.Select(d => d.Id));
            var cycles = string.Join(',', departmentGroup.OpenCycle.Split(',').Select(GetXingQi));

            //var owids = entity.Workers.Split(',').Select(int.Parse).ToList();
            //var oldWorkers = await _cheapContext.Workers.Where(w => owids.Contains(w.Id)).Select(w => w.RemoteId).ToListAsync();
            //var newWorkers = await _cheapContext.Workers.Where(w => wids.Contains(w.Id)).Select(w => w.RemoteId).ToListAsync();
            //var removed = oldWorkers.Except(newWorkers).ToList();
            //var added = newWorkers.Except(oldWorkers).ToList();
            //await ApiAddUserInGroup(entity.RemoteId, added, true);
            //data.RemoveAll(s => s.Key == "userIds");
            ////data.Add(KeyValuePair.Create("userIds", JsonConvert.SerializeObject(oldWorkers)));
            //foreach (var id in removed)
            //{
            //    data.Add(KeyValuePair.Create("userIds", id.ToString()));
            //}
            //if (removed.Count != 0)
            //{
            //    var response = await client.PostAsync("api/v1/user/remove/group", new FormUrlEncodedContent(data));
            //    await EnsureSuccess(response);
            //}
            entity.Name = departmentGroup.Name;
            entity.OpenCycle = cycles;

            await _cheapContext.SaveChangesAsync();

            return departmentGroup;
        }

        private async Task ApiAddUserInGroup(int groupRemoteId, List<int> userRemoteIds, bool added)
        {
            var client = _httpClientFactory.CreateClient("api");
            var data = new List<KeyValuePair<string, string>>();
            Sign(data);
            data.Add(KeyValuePair.Create("groupId", groupRemoteId.ToString()));
            //data.Add(KeyValuePair.Create("userIds", JsonConvert.SerializeObject(newWorkers)));
            foreach (var id in userRemoteIds)
            {
                data.Add(KeyValuePair.Create("userIds", id.ToString()));
            }
            if (userRemoteIds.Count != 0)
            {
                var url = $"api/v1/user/{(added ? "add" : "remove")}/group";
                var response = await client.PostAsync(url, new FormUrlEncodedContent(data));
                await EnsureSuccess(response);
            }
        }

        public async Task DeleteDepartmentGroup(int departmentGroupId)
        {
            var entity = await _cheapContext.DepartmentGroups.FindAsync(departmentGroupId);

            if (entity != null)
            {
                _cheapContext.DepartmentGroups.Remove(entity);
                await _cheapContext.SaveChangesAsync();
            }
        }

        public async Task<PagedResult<CompanyViewModel>> GetCompanys(CompanyFilter filter)
        {
            if (filter.id.HasValue)
            {
                var company = await _cheapContext.Companies.Include(c => c.Organization).FirstAsync(c => c.Id == filter.id);
                return SinglePageResult(new CompanyViewModel
                {
                    Address = company.Address,
                    Contact = company.Contact,
                    ContactPhoneNumber = company.ContactPhoneNumber,
                    Id = company.Id,
                    Name = company.Name,
                    OrganizationId = company.Organization.Id,
                    OrganizationName = company.Organization.Name,
                    Status = company.Status
                });
            }

            IQueryable<Company> companies = _cheapContext.Companies.Include(c => c.Organization);

            if (!string.IsNullOrEmpty(filter.name))
            {
                companies = companies.Where(c => c.Name.Contains(filter.name));
            }
            if (!string.IsNullOrEmpty(filter.organizationName))
            {
                companies = companies.Where(c => c.Organization.Name.Contains(filter.organizationName));
            }
            return await companies.Select(company => new CompanyViewModel
            {
                Address = company.Address,
                Contact = company.Contact,
                ContactPhoneNumber = company.ContactPhoneNumber,
                Id = company.Id,
                Name = company.Name,
                OrganizationId = company.Organization.Id,
                OrganizationName = company.Organization.Name,
                Status = company.Status
            })
                .PagingAsync(filter.page, filter.rows);
        }

        public async Task<CompanyViewModel> AddCompany(CompanyViewModel company)
        {
            var entity = _entityMapper.Map<CompanyViewModel, Company>(company);
            entity.Organization = await _cheapContext.Organizations.FindAsync(company.OrganizationId);
            _cheapContext.Companies.Add(entity);

            await _cheapContext.SaveChangesAsync();

            company.Id = entity.Id;
            return company;
        }

        public async Task<CompanyViewModel> UpdateCompany(CompanyViewModel company)
        {
            var entity = await _cheapContext.Companies.FindAsync(company.Id);
            _entityMapper.Map(company, entity);
            entity.Organization = await _cheapContext.Organizations.FindAsync(company.OrganizationId);

            await _cheapContext.SaveChangesAsync();

            return company;
        }

        public async Task DeleteCompany(int companyId)
        {
            var entity = await _cheapContext.Companies.FindAsync(companyId);

            if (entity != null)
            {
                _cheapContext.Companies.Remove(entity);
                await _cheapContext.SaveChangesAsync();
            }
        }

        public async Task<PagedResult<OrganizationViewModel>> GetOrganizations(OrganizationFilter filter)
        {
            if (filter.id.HasValue)
            {
                var organization = await _cheapContext.Organizations.FindAsync(filter.id);
                return SinglePageResult(_entityMapper.Map<Organization, OrganizationViewModel>(organization));
            }


            IQueryable<Organization> organizations = _cheapContext.Organizations;
            if (!string.IsNullOrEmpty(filter.name))
            {
                organizations = organizations.Where(o => o.Name.Contains(filter.name));
            }
            if (filter.Status == 1)
            {
                organizations = organizations.Where(o => o.Status == 1);
            }

            return await organizations.Select(organization =>
                    _entityMapper.Map<Organization, OrganizationViewModel>(organization))
                .PagingAsync(filter.page, filter.rows);
        }

        public async Task<OrganizationViewModel> AddOrganization(OrganizationViewModel organization)
        {
            var entity = _entityMapper.Map<OrganizationViewModel, Organization>(organization);

            _cheapContext.Organizations.Add(entity);

            await _cheapContext.SaveChangesAsync();

            organization.Id = entity.Id;
            return organization;
        }

        public async Task<OrganizationViewModel> UpdateOrganization(OrganizationViewModel organization)
        {
            var entity = await _cheapContext.Organizations.FindAsync(organization.Id);

            _entityMapper.Map(organization, entity);

            await _cheapContext.SaveChangesAsync();

            return organization;
        }

        public async Task DeleteOrganization(int organizationId)
        {
            var entity = await _cheapContext.Organizations.FindAsync(organizationId);

            if (entity != null)
            {
                _cheapContext.Organizations.Remove(entity);
                await _cheapContext.SaveChangesAsync();
            }
        }

        public async Task<PagedResult<BanCiViewModel>> GetBanCis(BanCiFilter filter)
        {
            if (filter.id.HasValue)
            {
                var banci = await _cheapContext.BanCis.FindAsync(filter.id);
                return SinglePageResult(new BanCiViewModel
                {
                    Id = banci.Id,
                    Name = banci.Name,
                    TimePeriods = await FindTimePeriodsByIds(banci.TimePeriods)
                });
            }

            IQueryable<BanCi> banCis = _cheapContext.BanCis;
            PagedResult<BanCi> result;
            if (!string.IsNullOrEmpty(filter.name))
            {
                result = await banCis.Where(w => w.Name.Contains(filter.name)).PagingAsync(filter.page, filter.rows);
            }
            else
            {
                result = await banCis.PagingAsync(filter.page, filter.rows);
            }

            var viewResult = new PagedResult<BanCiViewModel>
            {
                pagesize = result.pagesize,
                page = result.page,
                records = result.records,
                rows = new List<BanCiViewModel>()
            };

            foreach (var b in result.rows)
            {
                viewResult.rows.Add(new BanCiViewModel
                {
                    Id = b.Id,
                    Name = b.Name,
                    TimePeriods = await FindTimePeriodsByIds(b.TimePeriods)
                });
            }

            return viewResult;
        }

        public async Task<BanCiViewModel> AddBanCi(BanCiViewModel banCi)
        {
            var entity = new BanCi
            {
                CreateDateTime = DateTime.Now,
                Name = banCi.Name,
                TimePeriods = string.Join(',', banCi.TimePeriods.Select(t => t.Id))
            };

            _cheapContext.BanCis.Add(entity);

            await _cheapContext.SaveChangesAsync();

            banCi.Id = entity.Id;
            return banCi;
        }

        public async Task<BanCiViewModel> UpdateBanCi(BanCiViewModel banCi)
        {
            var entity = await _cheapContext.BanCis.FindAsync(banCi.Id);

            entity.Name = banCi.Name;
            entity.TimePeriods = string.Join(',', banCi.TimePeriods.Select(t => t.Id));

            await _cheapContext.SaveChangesAsync();

            return banCi;
        }

        public async Task DeleteBanCi(int banCiId)
        {
            var entity = await _cheapContext.BanCis.FindAsync(banCiId);

            if (entity != null)
            {
                _cheapContext.BanCis.Remove(entity);
                await _cheapContext.SaveChangesAsync();
            }
        }

        private async Task<List<TimePeriodViewModel>> FindTimePeriodsByIds(string ids)
        {
            var timePeriodIds = ids.Split(',').Select(int.Parse);
            var timePeriods = await _cheapContext.TimePeriods
                .Where(t => timePeriodIds.Contains(t.Id))
                .Select(t => _entityMapper.Map<TimePeriod, TimePeriodViewModel>(t))
                .ToListAsync();
            return timePeriods;
        }

        public async Task<PagedResult<PaiBanViewModel>> GetPaiBans(PaiBanFilter filter)
        {

            if (filter.id.HasValue)
            {
                var paiban = await _cheapContext.PaiBans
                    .Include(p => p.Worker)
                    .Include(p => p.Company)
                    .Include(p => p.BanCi)
                    .FirstAsync(p => p.Id == filter.id);
               
                var view = new PaiBanViewModel
                {
                    Id = paiban.Id,
                    Date = paiban.Date,
                    Worker = paiban.Worker != null ? _entityMapper.Map<Worker, WorkerViewModel>(paiban.Worker) : null,
                    BanCi = new BanCiViewModel
                    {
                        Id = paiban.BanCi.Id,
                        Name = paiban.BanCi.Name,
                    },
                    BanCiId = paiban.BanCiId,
                    BanciName = paiban.BanCi.Name,
                    Company = paiban.Company?.Name, //?? p.Worker.Company.Name,
                    CompanyId = paiban.CompanyId,
                    DateEnd = paiban.DateEnd,
                    DateStart = paiban.DateStart
                };

                var timePeriods = await FindTimePeriodsByIds(paiban.BanCi.TimePeriods);

                view.BanCi.TimePeriods = timePeriods;

                return SinglePageResult(view);
            }
            
            IQueryable<PaiBan> paiBans;
            if (filter.type == "1")
            {
                paiBans= _cheapContext.PaiBans.Where(p => p.CompanyId != null)
                .Include(p => p.Worker)
                .Include(p => p.Company)
                .Include(p => p.BanCi);
            }else
            {
                paiBans = _cheapContext.PaiBans.Where(p => p.WorkerId != null)
              .Include(p => p.Worker)
              .Include(p => p.Company)
              .Include(p => p.BanCi);
            }

            if(!string.IsNullOrEmpty(filter.name))
            {
                paiBans = paiBans.Where(p => p.BanCi.Name.Contains(filter.name));
            }
            var result = await paiBans.PagingAsync(filter.page, filter.rows);

            var viewResult = new PagedResult<PaiBanViewModel>
            {
                page = result.page,
                pagesize = result.pagesize,
                records = result.records,
                rows = new List<PaiBanViewModel>(result.rows.Count)
            };
            foreach (var p in result.rows)
            {
                viewResult.rows.Add(new PaiBanViewModel
                {
                    Id = p.Id,
                    Date = p.Date,
                    Worker = p.Worker != null ? _entityMapper.Map<Worker, WorkerViewModel>(p.Worker) : null,
                    BanCi = new BanCiViewModel
                    {
                        Id = p.BanCi.Id,
                        Name = p.BanCi.Name,
                        TimePeriods = await FindTimePeriodsByIds(p.BanCi.TimePeriods)
                    },
                    BanCiId = p.BanCiId,
                    BanciName = p.BanCi.Name,
                    Company = p.Company?.Name, //?? p.Worker.Company.Name,
                    CompanyId = p.CompanyId,
                    DateEnd = p.DateEnd,
                    DateStart = p.DateStart
                });
            }

            return viewResult;
        }

        public async Task<PaiBanViewModel> AddPaiBan(PaiBanViewModel paiBan)
        {
            var entity = new PaiBan
            {
                CreateDateTime = DateTime.Now,
                Date = paiBan.Date,
                //Worker = _entityMapper.Map<WorkerViewModel, Worker>(paiBan.Worker)
                DateEnd = paiBan.DateEnd,
                DateStart = paiBan.DateStart,
                WorkerId = paiBan.WorkerId,
                BanCiId = paiBan.BanCiId,
                CompanyId = paiBan.CompanyId,
            };
            //var worker = await _cheapContext.Workers.FindAsync(paiBan.Worker.Id);
            //entity.Worker = worker;
            //var banci = await _cheapContext.BanCis.FindAsync(paiBan.BanCi.Id);
            //entity.BanCi = banci;

            _cheapContext.PaiBans.Add(entity);

            await _cheapContext.SaveChangesAsync();

            paiBan.Id = entity.Id;
            return paiBan;
        }

        public async Task<PaiBanViewModel> UpdatePaiBan(PaiBanViewModel paiBan)
        {
            var entity = await _cheapContext.PaiBans.FindAsync(paiBan.Id);

            //var worker = _cheapContext.Entry(entity).Property<int?>("WorkerId");
            //var banci = _cheapContext.Entry(entity).Property<int?>("BanCiId");

            //if (paiBan.BanCi.Id != banci.CurrentValue)
            //{
            //    banci.CurrentValue = paiBan.BanCi.Id;
            //}

            //if (paiBan.Worker.Id != worker.CurrentValue)
            //{
            //    worker.CurrentValue = paiBan.Worker.Id;
            //}

            entity.Date = paiBan.Date;
            entity.CompanyId = paiBan.CompanyId;
            entity.WorkerId = paiBan.WorkerId;
            entity.DateStart = paiBan.DateStart;
            entity.DateEnd = paiBan.DateEnd;
            entity.BanCiId = paiBan.BanCiId;
            await _cheapContext.SaveChangesAsync();
            return paiBan;
        }

        public async Task DeletePaiBan(int paiBanId)
        {
            var entity = await _cheapContext.PaiBans.FindAsync(paiBanId);

            if (entity != null)
            {
                _cheapContext.PaiBans.Remove(entity);
                await _cheapContext.SaveChangesAsync();
            }
        }

        public async Task<PagedResult<TimePeriodViewModel>> GetTimePeriods(TimePeriodFilter filter)
        {
            if (filter.id.HasValue)
            {
                var timePeriod = await _cheapContext.TimePeriods.FindAsync(filter.id);
                return SinglePageResult(_entityMapper.Map<TimePeriod, TimePeriodViewModel>(timePeriod));
            }

            IQueryable<TimePeriod> timePeriods = _cheapContext.TimePeriods;
            if(!string.IsNullOrEmpty(filter.name))
            {
                return await timePeriods.Where(w => w.PeriodName.Contains(filter.name)).Select(timePeriod => _entityMapper.Map<TimePeriod, TimePeriodViewModel>(timePeriod))
               .PagingAsync(filter.page, filter.rows);
            }

            return await timePeriods.Select(timePeriod => _entityMapper.Map<TimePeriod, TimePeriodViewModel>(timePeriod))
                .PagingAsync(filter.page, filter.rows);
        }

        public async Task<TimePeriodViewModel> AddTimePeriod(TimePeriodViewModel timePeriod)
        {
            var entity = _entityMapper.Map<TimePeriodViewModel, TimePeriod>(timePeriod);

            _cheapContext.TimePeriods.Add(entity);

            await _cheapContext.SaveChangesAsync();

            timePeriod.Id = entity.Id;
            return timePeriod;
        }

        public async Task<TimePeriodViewModel> UpdateTimePeriod(TimePeriodViewModel timePeriod)
        {
            var entity = await _cheapContext.TimePeriods.FindAsync(timePeriod.Id);

            _entityMapper.Map(timePeriod, entity);

            await _cheapContext.SaveChangesAsync();

            return timePeriod;
        }

        public async Task DeleteTimePeriod(int timePeriodId)
        {
            var entity = await _cheapContext.TimePeriods.FindAsync(timePeriodId);

            if (entity != null)
            {
                _cheapContext.TimePeriods.Remove(entity);
                await _cheapContext.SaveChangesAsync();
            }
        }

        private static string GetXingQi(string xingqi)
        {
            xingqi = xingqi.Trim();

            return xingqi;
        }

        private PagedResult<T> SinglePageResult<T>(T result)
        {
            return new PagedResult<T>(0, 1)
            {
                rows = new List<T> { result }
            };
        }

        private static void Sign(List<KeyValuePair<string, string>> param)
        {
            var timestamp = $"{(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds:F0}000";
            param.Add(KeyValuePair.Create("timestamp", timestamp));
            string appkey = ConfigurationManager.AppSettings["AppKey"];
            string appsecret = ConfigurationManager.AppSettings["AppSecret"];

            param.Add(KeyValuePair.Create("app_key", appkey));//hantao e399af3084f4b494
            //param.Sort();
            var str1 = string.Join('&', param.Select(kv => $"{kv.Key}={kv.Value}"));
            var str2 = str1 + "#SECRET";
            using (var md5 = MD5.Create())
            {
                var datas = md5.ComputeHash(Encoding.UTF8.GetBytes($"{timestamp}#" + appsecret));//hantao 0bb30af9ea12d0d2b2594795b3e618da
                param.Add(KeyValuePair.Create("sign", string.Join("", datas.Select(b => b.ToString("x2")))));
            }
        }

        private static string BuildUrl(List<KeyValuePair<string, string>> param)
        {
            var query = string.Join('&', param.Select(kv => $"{kv.Key}={kv.Value}"));
            if (string.IsNullOrEmpty(query))
            {
                return string.Empty;
            }

            return $"?{query}";
        }

        private static async Task<ApiResponse<dynamic>> EnsureSuccess(HttpResponseMessage response)
        {
            response.EnsureSuccessStatusCode();
            var res = await response.Content.ReadAsStringAsync();
            var result = JsonConvert.DeserializeObject<ApiResponse<dynamic>>(res);
            if(result.Desc== "user.not-exist")
            {
                return result;
            }
            if (result.Code != "200")
            {
                string message = string.Empty;
                switch(result.Code)
                {
                    case "30001":
                        message = "参数不合法 ";
                        break;
                    case "30002":
                        message = "图片中未检测到人脸 ";
                        break;
                    case "30004":
                        message = "缺失参数 ";
                        break;
                    case "30005":
                        message = "图片格式不合格";
                        break;
                    case "50001":
                        message = "服务器同步报错";
                        break;
                    case "50002":
                        message = "服务器内部错误";
                        break;
                    case "50003":
                        message = "批处理报错";
                        break;
                    case "50004":
                        message = "请求方法无效";
                        break;
                    default:
                        message = "未知错误";
                        break;

                }
                throw new DomainException(message + result.Desc);
            }

            return result;
        }
    }

}
